package yang.yu.sunny.domain;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.dayatang.domain.AbstractEntity;
import org.dayatang.domain.InstanceFactory;
import yang.yu.sunny.EventBus;

import javax.persistence.Entity;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import java.util.*;

/**
 * 产品
 * Created by yyang on 16/3/15.
 */
@Entity
@Table(name = "products")
public class Product extends AbstractEntity {

    private String name;

    @ManyToOne
    private ProductCategory category;

    protected Product() {
    }

    public Product(String name, ProductCategory category) {
        this.name = name;
        this.category = category;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public ProductCategory getCategory() {
        return category;
    }

    public void setCategory(ProductCategory category) {
        this.category = category;
    }

    public void changeName(String newName) {
        String oldName = name;
        name = newName;
        save();
        InstanceFactory.getInstance(EventBus.class)
                .post(new ProductNameChangedEvent(getId(), oldName, newName));
    }

    /**
     * 获得指定日期的单价
     * @param time
     * @return
     */
    public Optional<Double> getUnitPriceAtTime(Date time) {
        return ProductPrice.getPriceOfProductAtTime(this, time);
    }

    /**
     * 获得当前单价
     * @return
     */
    public Optional<Double> getCurrentUnitPrice() {
        return ProductPrice.getPriceOfProductAtTime(this, new Date());
    }

    public Set<ProductCategory> getCategories() {
        Set<ProductCategory> results = new HashSet<>();
        if (category == null) {
            return results;
        }
        results.add(category);
        Optional<ProductCategory> parentCategory = category.getParent();
        while (parentCategory.isPresent()) {
            results.add(parentCategory.get());
            parentCategory = parentCategory.get().getParent();
        }
        return results;
    }

    static List<Product> findByCategory(ProductCategory category) {
        return getRepository().createCriteriaQuery(Product.class)
                .eq("category", category)
                .list();
    }

    public static Optional<Product> get(Long id) {
        return Optional.ofNullable(getRepository().get(Product.class, id));
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }

        if (!(o instanceof Product)) {
            return false;
        }

        Product product = (Product) o;

        return new EqualsBuilder()
                .append(getName(), product.getName())
                .append(getCategory(), product.getCategory())
                .isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 37)
                .append(getName())
                .append(getCategory())
                .toHashCode();
    }

    @Override
    public String toString() {
        return getName();
    }
}
